package com.ff.xyh.consumer.chatroom.controller;

import com.ff.xyh.common.servicebase.config.MyApplicationContextAware;
import com.ff.xyh.common.vo.message.ActionTypeAndRoomMessage;
import com.ff.xyh.common.vo.message.RoomMessageVo;
import com.ff.xyh.consumer.chatroom.config.RoomRabbitConfig;
import com.ff.xyh.consumer.chatroom.config.Rooms;
import com.ff.xyh.consumer.chatroom.config.UserLock;
import com.ff.xyh.consumer.chatroom.config.Users;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.List;
import java.util.Map;


@ServerEndpoint(value = "/chatroom")
@Component
public class RoomUserController{


    private Session session;
    private String userId;
    private String roomId;

    private static RedisTemplate redisTemplate;
    private static RabbitTemplate rabbitTemplate;

    public Session getSession() {
        return session;
    }
    public String getUserId() {
        return userId;
    }
    public String getRoomId() {
        return roomId;
    }

    public RoomUserController() {
        if (redisTemplate == null) {
            if (MyApplicationContextAware.getApplicationContext() != null) {
                redisTemplate = MyApplicationContextAware.getBean("redisTemplate", RedisTemplate.class);
            }
        }
        if (rabbitTemplate == null) {
            if (MyApplicationContextAware.getApplicationContext() != null) {
                rabbitTemplate = MyApplicationContextAware.getBean("rabbitTemplate", RabbitTemplate.class);
            }
        }
    }

    /**
     * 一个用户连接时生成一个controller 一个controller也会包含一个session
     * 用户登录后保持连接 可以做在线业务
     */
    @OnOpen
    public void onOpen(Session session) {
        Map<String, List<String>> requestParameterMap = session.getRequestParameterMap();
        String roomId = requestParameterMap.get("roomId").get(0);
        String userId = requestParameterMap.get("userId").get(0);
        this.session = session;
        this.userId = userId;
        this.roomId = roomId;
        System.out.println("userId:" + userId + "\n" +
                "roomId:" + roomId);
        // 当服务器存在该用户时，先断开用户连接，再将 userId 和 当前服务器的 用户 routingKey 绑定到redis
        if (redisTemplate.hasKey(this.userId)) {
            System.out.println("用户已被登录");
            new UserLock(this.userId);
            String userRoutingKey = (String) redisTemplate.opsForValue().get(userId);
            rabbitTemplate.convertAndSend(
                    RoomRabbitConfig.EXCHANGE_DIRECT_CHAT,
                    userRoutingKey,
                    ActionTypeAndRoomMessage.type(16)
                            .data("message", new RoomMessageVo()
                                    .setId(RoomRabbitConfig.ROUTING_KEY_USER_LOCK_1)
                                    .setToUserId(userId)
                                    .setRoomId(roomId)
                                    .setMessage("连接被占用，请重新连接。如不是您授权的操作，请联系客服冻结"))
            );
            try {
                UserLock.getLocks().get(this.userId).waitForConfirm(5 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            UserLock.getLocks().remove(this.userId);
            redisTemplate.opsForValue().set(this.userId, RoomRabbitConfig.ROUTING_KEY_USER_1);
        } else {
            System.out.println("用户没有被登录");
            redisTemplate.opsForValue().set(this.userId, RoomRabbitConfig.ROUTING_KEY_USER_1);
        }
        Map<String, RoomUserController> users = Users.getUsers();
        synchronized (users) {
            users.put(this.userId, this);
        }

        // 看看聊天室是否已被创建 若是 则将用户id添加到所在服务器的 rooms
        if (redisTemplate.hasKey(roomId)) {
            // 获取房间所在服务器的路由值
            String roomRoutingKey = (String) redisTemplate.opsForValue().get(roomId);
            RoomMessageVo roomMessageVo = new RoomMessageVo();
            roomMessageVo.setRoomId(this.roomId).setUserId(this.userId);
            rabbitTemplate.convertAndSend(
                    RoomRabbitConfig.EXCHANGE_DIRECT_CHAT,
                    roomRoutingKey,
                    ActionTypeAndRoomMessage.type(5)
                            .data("message", roomMessageVo)
            );
        } else {
            String roomRoutingKey = RoomRabbitConfig.ROUTING_KEY_ROOM_1;
            RoomMessageVo roomMessageVo = new RoomMessageVo();
            roomMessageVo.setRoomId(this.roomId).setUserId(this.userId);
            rabbitTemplate.convertAndSend(
                    RoomRabbitConfig.EXCHANGE_DIRECT_CHAT,
                    roomRoutingKey,
                    ActionTypeAndRoomMessage.type(5)
                            .data("message", roomMessageVo)
            );
//            CopyOnWriteArraySet<String> roomUsers = null;
//            Map<String, CopyOnWriteArraySet<String>> rooms = Rooms.getRooms();
//            // 第一个链接聊天室
//            synchronized (rooms) {
//                if (!rooms.containsKey(this.roomId)) {
//                    roomUsers = new CopyOnWriteArraySet<>();
//                    rooms.put(this.roomId, roomUsers);
//                    // roomId 和 当前服务器的 房间路由 绑定到redis
//                    redisTemplate.opsForValue().set(this.roomId, RoomRabbitConfig.ROUTING_KEY_ROOM_1);
//                }
//            }
//            try {
//                if (roomUsers == null || ! roomUsers.add(this.userId)) {
//                    MessageOwnerAndRoomMessage messageToUser =
//                            MessageOwnerAndRoomMessage.type(7)
//                                    .data("message",
//                                            new RoomMessageVo()
//                                                    .setMessage("房间连接失败，请退出重试")
//                                                    .setRoomId(roomId)
//                                    );
//                    session.getAsyncRemote().sendObject(messageToUser);
//                    session.close();
//                } else {
//                    MessageOwnerAndRoomMessage messageToUser =
//                            MessageOwnerAndRoomMessage.type(6)
//                                    .data("message",
//                                            new RoomMessageVo()
//                                                    .setMessage("成功进入房间")
//                                                    .setRoomId(roomId)
//                                    );
//                    session.getAsyncRemote().sendObject(messageToUser);
//                }
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
        }



    }

    @OnClose
    public void onClose() {
        // 除去服务器和redis中保存的用户信息
        Map<String, RoomUserController> users = Users.getUsers();
        synchronized (users) {
            users.remove(this.userId);
        }

        redisTemplate.opsForValue().getOperations().delete(this.userId);

//        redis中有存在的房间信息
        if (redisTemplate.hasKey(this.roomId)) {
            // 获取房间所在服务器的路由值
            String roomRoutingKey = (String) redisTemplate.opsForValue().get(this.roomId);
            RoomMessageVo message = new RoomMessageVo();
            message.setRoomId(this.roomId).setUserId(this.userId);
            rabbitTemplate.convertAndSend(
                    RoomRabbitConfig.EXCHANGE_DIRECT_CHAT,
                    roomRoutingKey,
                    ActionTypeAndRoomMessage.type(8)
                            .data("message", message)
            );
        } else { // 没有存在的房间信息 尝试性删除当前服务器对应的房间信息
            Rooms.getRooms().remove(this.roomId);
        }

    }

    /**
     * 服务端接收消息
     * @param msg
     * @param session
     */
    // 客户端向服务端
    @OnMessage
    public void onMessage(String msg, Session session) {

        /** 如果是将用户踢出群 则消息体 userId 对应 operatorId toUserId存入bannerId */
        // {"actionType":5,"messageBody":{"message":{"roomId":"12312345","message":"这是消息","userId":"65432211"}}
//        Gson gson = new Gson();
//        MessageOwnerAndRoomMessage message = gson.fromJson(msg, MessageOwnerAndRoomMessage.class);
        // type messageText
//          9-这是消息1
        System.out.println(msg);
        String[] split = msg.split("-");
//        MessageOwnerAndRoomMessage message = JSON.parseObject(msg, MessageOwnerAndRoomMessage.class);
        ActionTypeAndRoomMessage message = new ActionTypeAndRoomMessage();
        message.setActionType(Integer.parseInt(split[0]))
                .data("message", new RoomMessageVo().setMessage(split[1]));
                // message中的messageBody应包含有一个RoomMessage对象
        System.out.println("服务器端接收到的消息体： " + message);
        RoomMessageVo roomMessageVo = message.getMessageBody().get("message");
        if (message.getActionType() == 12)
            roomMessageVo.setToUserId(split[2]);
        roomMessageVo.setRoomId(this.roomId).setUserId(this.userId);
        // 获取房间所在服务器的路由值
        String roomRoutingKey = (String) redisTemplate.opsForValue().get(this.roomId);
        rabbitTemplate.convertAndSend(
                RoomRabbitConfig.EXCHANGE_DIRECT_CHAT,
                roomRoutingKey,
                message
        );
    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
        System.out.println("Room Server Error");
    }

}